package org.liang.code.rabbitMQ.发布订阅模式;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.liang.code.rabbitMQ.utils.RabbitConstant;
import org.liang.code.rabbitMQ.utils.RabbitUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.time.LocalDate;
import java.util.Random;
import java.util.concurrent.TimeoutException;

public class WeatherBureau {

    private static final Logger logger = LoggerFactory.getLogger(WeatherBureau.class);

    public static void main(String[] args) throws IOException, TimeoutException {

        try (
                Connection connection = RabbitUtils.getConnection();
                Channel channel = connection.createChannel()
        ) {
            // 声明一个交换机，使用 RabbitMQ 通道的 exchangeDeclare 方法。
            // 参数解释：
            // 1. RabbitConstant.EXCHANGE_WEATHER：交换机的名称，由常量类 RabbitConstant 定义，用于后续消息的发布和路由。
            // 2. "fanout"：交换机的类型，这里是扇形（fanout）类型，这种类型会将接收到的消息广播到所有与之绑定的队列中。
            // 3. true：表示该交换机是持久化的，即 RabbitMQ 服务器重启后，交换机不会丢失。
            channel.exchangeDeclare(RabbitConstant.EXCHANGE_WEATHER_FANOUT, "fanout", true);

            // 声明一个队列，使用 RabbitMQ 通道的 queueDeclare 方法。
            // 参数解释：
            // 1. RabbitConstant.QUEUE_BAIDU：队列的名称，由常量类 RabbitConstant 定义，用于存储接收到的消息。
            // 2. true：表示该队列是持久化的，即 RabbitMQ 服务器重启后，队列不会丢失，队列中的消息也会保留。
            // 3. false：表示该队列不是排他性的，即多个连接可以同时访问该队列。
            // 4. false：表示该队列在不再使用时不会自动删除。
            // 5. null：表示不使用额外的队列参数。
            channel.queueDeclare(RabbitConstant.QUEUE_BAIDU, true, false, false, null);

            // 将队列绑定到交换机上，使用 RabbitMQ 通道的 queueBind 方法。
            // 参数解释：
            // 1. RabbitConstant.QUEUE_BAIDU：要绑定的队列名称，由常量类 RabbitConstant 定义。
            // 2. RabbitConstant.EXCHANGE_WEATHER：要绑定到的交换机名称，由常量类 RabbitConstant 定义。
            // 3. ""：绑定键，在扇形交换机中，绑定键会被忽略，因为扇形交换机会将消息广播到所有绑定的队列。
            channel.queueBind(RabbitConstant.QUEUE_BAIDU, RabbitConstant.EXCHANGE_WEATHER_FANOUT, "");

            channel.queueDeclare(RabbitConstant.QUEUE_SINA, true, false, false, null);
            channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_FANOUT, "");

            Random random = new Random();

            String[] cities = { "Beijing", "New York", "Tokyo", "Paris", "London" };
            String[] countries = { "China", "USA", "Japan", "France", "UK" };
            String[] weathers = { "Sunny", "Rainy", "Cloudy", "Snowy" };

            while (true) {
                String weather = weathers[random.nextInt(weathers.length)];
                // 根据天气类型生成合理温度
                int maxTemp, minTemp;
                switch (weather) {
                    case "Sunny":
                        maxTemp = random.nextInt(11) + 25; // 25-35℃
                        minTemp = maxTemp - 10; // 日温差约10℃
                        break;
                    case "Rainy":
                        maxTemp = random.nextInt(6) + 20; // 20-25℃
                        minTemp = random.nextInt(10) + 10; // 10-20℃
                        break;
                    case "Cloudy":
                        maxTemp = random.nextInt(9) + 20; // 20-28℃
                        minTemp = random.nextInt(8) + 15; // 15-22℃
                        break;
                    default: // Snowy
                        maxTemp = random.nextInt(6) - 5; // -5~0℃
                        minTemp = random.nextInt(6) - 10; // -10~-5℃
                }
                int idx = random.nextInt(countries.length);
                String json = String.format(
                        "{\"date\":\"%s\", \"country\":\"%s\", \"city\":\"%s\", \"weather\":\"%s\", " +
                                "\"minTemp\":%d, \"maxTemp\":%d}",
                        LocalDate.now(),
                        countries[idx],
                        cities[idx],
                        weather,
                        minTemp,
                        maxTemp);
                logger.info("天气信息：{}", json);
                // 调用 RabbitMQ 通道的 basicPublish 方法，将生成的天气预报 JSON 数据发送到指定的交换机。
                // 参数解释：
                // 1. RabbitConstant.EXCHANGE_WEATHER：指定要将消息发布到的交换机名称，由常量类 RabbitConstant 定义。
                // 2. ""：路由键，发布订阅模式不需要。
                // 3. null：消息的属性，传入 null 表示使用默认的消息属性。
                // 4. json.getBytes()：要发送的消息内容，将之前生成的 JSON 字符串转换为字节数组。
                channel.basicPublish(RabbitConstant.EXCHANGE_WEATHER_FANOUT, "", null, json.getBytes());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}
